home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1996-09-09 | 24.6 KB | 742 lines | [ TEXT/CCL2]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; MidiShare.lisp ;; ;; Copyright (c) 1993, GRAME. All rights reserved. ;; ;; Common Lisp interface to MidiShare 1.68. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;==================================================================================== ;; Définition du package, importations et exportations ;;------------------------------------------------------------------------------------ (defpackage "MIDISHARE" (:use "COMMON-LISP" "CCL")) (in-package :midishare) (eval-when (:compile-toplevel :load-toplevel :execute) (let ((*warn-if-redefine* nil)) (require :ff))) (export '(typeNote typeKeyOn typeKeyOff typeKeyPress typeCtrlChange typeProgChange typeChanPress typePitchWheel typeSongPos typeSongSel typeClock typeStart typeContinue typeStop typeTune typeActiveSens typeReset typeSysEx typeStream typePrivate typeProcess typeDProcess typeQFrame typeReserved typeDead typeCtrl14b typeNonRegParam typeRegParam typeSeqNum typeText typeCopyright typeSeqName typeInstrName typeLyric typeMarker typeCuePoint typeChanPrefix typeEndTrack typeTempo typeSMPTEOffset typeTimeSign typeKeySign typeSpecific MIDIerrSpace MIDIerrRefNum MIDIerrBadType MIDIerrIndex ModemPort PrinterPort MidiExternalSync MidiSyncAnyPort Smpte24Fr Smpte25Fr Smpte30DF Smpte30Fr MIDIOpenAppl MIDICloseAppl MIDIChgName MIDIChgConnect MIDIOpenModem MIDICloseModem MIDIOpenPrinter MIDIClosePrinter MIDISyncStart MIDISyncStop MIDIChangeSync MidiGetVersion MidiCountAppls MidiGetIndAppl MidiGetNamedAppl MidiOpen MidiClose MidiGetName MidiSetName MidiGetInfo MidiSetInfo MidiGetFilter MidiSetFilter MidiGetRcvAlarm MidiSetRcvAlarm MidiGetApplAlarm MidiSetApplAlarm MidiConnect MidiIsConnected MidiGetPortState MidiSetPortState MidiFreeSpace MidiNewEv MidiCopyEv MidiFreeEv MidiSetField MidiGetField MidiAddField MidiCountFields MidiNewSeq MidiAddSeq MidiFreeSeq MidiClearSeq MidiApplySeq MidiGetTime MidiSendIm MidiSend MidiSendAt MidiCountEvs MidiGetEv MidiAvailEv MidiFlushEvs MidiReadSync MidiWriteSync MidiCall MidiTask MidiDTask MidiForgetTask MidiCountDTasks MidiFlushDTasks MidiExec1DTask MidiNewCell MidiFreeCell MidiTotalSpace MidiGrowSpace MidiShare link date type ref port chan xfield pitch vel dur xfields text firstEv lastEv FilterBit AcceptPort AcceptType AcceptChan)) (use-package 'midishare 'cl-user) ;;==================================================================================== ;; Some useful tools ;;------------------- (defun %%get-string (ps) "Same as %get-string but work with mac non-zone pointers" (let (name count) (setq count (%get-byte ps)) (setq name (make-string count)) (dotimes (i count) (setq ps (%inc-ptr ps 1)) (setf (aref name i) (coerce (%get-byte ps) 'character))) name)) ;; Records definitions (from MPW C MidiShare.h) ;;---------------------------------------------- ;; Extension record for typeSysEx events (defrecord TMidiSEX (link (:pointer TMidiSEX)) (data (:array :byte 12))) ;; Extension record for typePrivate, typeProcess and typeDProcess events (defrecord TMidiST (ptr1 :pointer) (ptr2 :pointer) (ptr3 :pointer) (ptr4 :pointer)) ;; Record for every MidiShare event (defrecord TMidiEv (link (:pointer TMidiEv)) (date :longint) (evtype :byte) (ref :byte) (port :byte) (chan :byte) (variant ((pitch :byte) (vel :byte) (dur :integer)) ((data0 :byte) (data1 :byte) (data2 :byte) (data3 :byte)) ((info :longint)) ((linkSE (:pointer TMidiSEX))) ((linkST (:pointer TMidiST))))) ;; Sequence header (defrecord TMidiSeq (first (:pointer TMidiEv)) ; first event (last (:pointer TMidiEv)) ; last event (undef1 :pointer) (undef2 :pointer) ) ;; Record for an input filter (defrecord TFilter (port (string 63)) ; 256-bits (evType (string 63)) ; 256-bits (channel (string 1)) ; 16-bits (unused (string 1))) ; 16-bits ;; Record for synchronisation informations (defrecord TSyncInfo (time :longint) (reenter :longint) (syncMode :unsigned-short) (syncLocked :byte) (syncPort :byte) (syncStart :longint) (syncStop :longint) (syncOffset :longint) (syncSpeed :longint) (syncBreaks :longint) (syncFormat :short)) ;; Record for smpte locations (defrecord TSmpteLocation (format :short) (hours :short) (minutes :short) (seconds :short) (frames :short) (fracs :short)) ;; Task Handle (for midiforgettask) (defrecord TTaskHdl (task (:pointer TMidiEv)) ) (defvar *taskhdl* (make-record :TTaskHdl)) ;; Set *midiShare* with the address of MidiShare Entry Point (address stored at boot time into low memory address $B8) (defvar *midiShare* (%get-ptr (%int-to-ptr #xB8)) "MidiShare entry point") ;; Constant definition for every type of MidiShare events (defconstant typeNote 0 "a note with pitch, velocity and duration") (defconstant typeKeyOn 1 "a key on with pitch and velocity") (defconstant typeKeyOff 2 "a key off with pitch and velocity") (defconstant typeKeyPress 3 "a key pressure with pitch and pressure value") (defconstant typeCtrlChange 4 "a control change with control number and control value") (defconstant typeProgChange 5 "a program change with program number") (defconstant typeChanPress 6 "a channel pressure with pressure value") (defconstant typePitchWheel 7 "a pitch bender with lsb and msb of the 14-bit value") (defconstant typePitchBend 7 "a pitch bender with lsb and msb of the 14-bit value") (defconstant typeSongPos 8 "a song position with lsb and msb of the 14-bit position") (defconstant typeSongSel 9 "a song selection with a song number") (defconstant typeClock 10 "a clock request (no argument)") (defconstant typeStart 11 "a start request (no argument)") (defconstant typeContinue 12 "a continue request (no argument)") (defconstant typeStop 13 "a stop request (no argument)") (defconstant typeTune 14 "a tune request (no argument)") (defconstant typeActiveSens 15 "an active sensing code (no argument)") (defconstant typeReset 16 "a reset request (no argument)") (defconstant typeSysEx 17 "a system exclusive with any number of data bytes. Leading $F0 and tailing $F7 are automatically supplied by MidiShare and MUST NOT be included by the user") (defconstant typeStream 18 "a special event with any number of data and status bytes sended without any processing") (defconstant typePrivate 19 "a private event for internal use with 4 32-bits arguments") (defconstant typeProcess 128 "an interrupt level task with a function adress and 3 32-bits arguments") (defconstant typeDProcess 129 "a foreground level task with a function adress and 3 32-bits arguments") (defconstant typeQFrame 130 "a quarter frame message with a type from 0 to 7 and a value") (defconstant typeCtrl14b 131) (defconstant typeNonRegParam 132) (defconstant typeRegParam 133) (defconstant typeSeqNum 134) (defconstant typeText 135) (defconstant typeCopyright 136) (defconstant typeSeqName 137) (defconstant typeInstrName 138) (defconstant typeLyric 139) (defconstant typeMarker 140) (defconstant typeCuePoint 141) (defconstant typeChanPrefix 142) (defconstant typeEndTrack 143) (defconstant typeTempo 144) (defconstant typeSMPTEOffset 145) (defconstant typeTimeSign 146) (defconstant typeKeySign 147) (defconstant typeSpecific 148) (defconstant typeReserved 149 "events reserved for futur use") (defconstant typedead 255 "a dead task. Used by MidiShare to forget and inactivate typeProcess and typeDProcess tasks") ;; Constant definition for every MidiShare error code (defconstant MIDIerrSpace -1 "too many applications") (defconstant MIDIerrRefNum -2 "bad reference number") (defconstant MIDIerrBadType -3 "bad event type") (defconstant MIDIerrIndex -4 "bad index") ;; Constant definition for the Macintosh serial ports (defconstant ModemPort 0 "Macintosh modem port") (defconstant PrinterPort 1 "Macintosh printer port") ;; Constant definition for the synchronisation modes (defconstant MidiExternalSync #x8000 "Bit-15 set for external synchronisation") (defconstant MidiSyncAnyPort #x4000 "Bit-14 set for synchronisation on any port") ;; Constant definition for SMPTE formats (defconstant Smpte24Fr 0 "24 frames per second SMPTE format") (defconstant Smpte25Fr 1 "25 frames per second SMPTE format") (defconstant Smpte30DF 2 "29.97 drop frame frames per second SMPTE format") (defconstant Smpte30Fr 3 "30 frames per second SMPTE format") ;; Constant definition for MidiShare world changes (defconstant MIDIOpenAppl 1 "an application was opened") (defconstant MIDICloseAppl 2 "an application was closed") (defconstant MIDIChgName 3 "an application name was changed") (defconstant MIDIChgConnect 4 "a connection was changed") (defconstant MIDIOpenModem 5 "Modem port was opened") (defconstant MIDICloseModem 6 "Modem port was closed") (defconstant MIDIOpenPrinter 7 "Printer port was opened") (defconstant MIDIClosePrinter 8 "Printer port was closed") (defconstant MIDISyncStart 9 "SMPTE synchronisation just start") (defconstant MIDISyncStop 10 "SMPTE synchronisation just stop") (defconstant MIDIChangeSync 11 "the synchronisation mode was changed") ;; Usefull macros to access MidiShare data structures and events ;;======================================================================================== ;; Macros to access MidiShare events fields ;;----------------------------------------- ;; access to common fields (defmacro link (e &optional (d nil d?)) "read or set the link of an event" (if d? `(rset ,e :TMidiEv.link ,d) `(rref ,e :TMidiEv.link))) (defmacro date (e &optional d) "read or set the date of an event" (if d `(rset ,e :TMidiEv.date ,d) `(rref ,e :TMidiEv.date))) (defmacro type (e &optional v) "read or set the type of an event. Be careful in modifying the type of an event" (if v `(rset ,e :TMidiEv.evType ,v) `(rref ,e :TMidiEv.evType))) (defmacro ref (e &optional v) "read or set the reference number of an event" (if v `(rset ,e :TMidiEv.ref ,v) `(rref ,e :TMidiEv.ref))) (defmacro port (e &optional v) "read or set the port number of an event" (if v `(rset ,e :TMidiEv.port ,v) `(rref ,e :TMidiEv.port))) (defmacro chan (e &optional v) "read or set the chan number of an event" (if v `(rset ,e :TMidiEv.chan ,v) `(rref ,e :TMidiEv.chan))) ;; fast access to extension fields for note, keyon and keyoff events (defmacro pitch (e &optional v) "read or set the pitch of an event (equivalent to field 0)" (if v `(rset ,e :TMidiEv.pitch ,v) `(rref ,e :TMidiEv.pitch))) (defmacro vel (e &optional v) "read or set the velocity of an event (equivalent to field 1)" (if v `(rset ,e :TMidiEv.vel ,v) `(rref ,e :TMidiEv.vel))) (defmacro dur (e &optional v) "read or set the duration of an event (equivalent to field 0)" (if v `(rset ,e :TMidiEv.dur ,v) `(rref ,e :TMidiEv.dur))) ;; access to extension fields (defmacro xfield (e &optional f v) "give the number of fields or read or set a particular field of an event" (if f (if v `(midiSetField ,e ,f ,v) `(midiGetField ,e ,f)) `(midiCountFields ,e))) ;; access to field list for sysex and other variable length events (defmacro xfields (e &optional v) (if v `(let ((e ,e)) (mapc #'(lambda (f) (midiaddfield e f)) ,v)) `(let (l (e ,e)) (dotimes (i (midicountfields e)) (push (midigetfield e i) l)) (nreverse l)) )) ;; access to field list as strings (for text events) (defmacro text (e &optional s) (if s `(xfields ,e (map 'list #'char-code ,s)) `(map 'string #'character (xfields ,e)) )) ;; Macros to access MidiShare sequences first and last event ;;---------------------------------------------------------- (defmacro firstEv (s &optional (e nil e?)) "read or set the first event of a sequence" (if e? `(rset ,s :TMidiSeq.first ,e) `(rref ,s :TMidiSeq.first))) (defmacro lastEv (s &optional (e nil e?)) "read or set the last event of a sequence" (if e? `(rset ,s :TMidiSeq.last ,e) `(rref ,s :TMidiSeq.last))) ;; Macros to access input filters ;;----------------------------------------- (defun FilterBit (p n &optional (val nil val?)) (if val? (%put-byte p (if val (logior (%get-byte p (ash n -3)) (ash 1 (logand n 7))) (logandc2 (%get-byte p (ash n -3)) (ash 1 (logand n 7))) ) (ash n -3)) (logbitp (logand n 7) (%get-byte p (ash n -3))))) (defmacro AcceptPort (f p &rest s) `(filterBit ,f ,p ,@s)) (defmacro AcceptType (f p &rest s) `(filterBit (%inc-ptr ,f 32) ,p ,@s)) (defmacro AcceptChan (f p &rest s) `(filterBit (%inc-ptr ,f 64) ,p ,@s)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -- MidiShare calls -- ;; ;; Interface description for a Pascal PROCEDURE ;; with a word and a pointer parameter ;; (ff-call *midiShare* :word <arg1> :ptr <arg2> :d0 <routine#>) ;; ;; Interface description for a Pascal FUNCTION ;; with a word and a pointer parameter and a word result ;; (ff-call *midiShare* :word 0 :word <arg1> :ptr <arg2> :d0 <routine#> :word) ;; ;; Interface description for a Pascal FUNCTION ;; with a word and a pointer parameter and a pointer result ;; (ff-call *midiShare* :ptr (%null-ptr) :word <arg1> :ptr <arg2> :d0 <routine#> :ptr) ;; ;; General informations about MidiShare (defun MidiShare () "Test if MidiShare is intalled" (and (= (%get-word *midiShare*) #xD080) (= (%get-word *midiShare* 2) #xD080))) (defmacro MidiGetVersion () "Give MidiShare version as a fixnum. For example 168 as result means : version 1.68" `(block nil (ff-call *midiShare* :word 0 :d0 0 :word))) ;; Informations about currently registred MidiShare client application (defmacro MidiCountAppls () "Give the number of registered MidiShare client applications" `(block nil (ff-call *midiShare* :word 0 :d0 1 :word))) (defmacro MidiGetIndAppl (index) "Give the reference number of a MidiShare application from its index, a fixnum between 1 and (MidiCountAppls)" `(block nil (ff-call *midiShare* :word 0 :word ,index :d0 2 :word))) (defmacro MidiGetNamedAppl (name) "Give the reference number of a MidiShare application from its name" `(with-pstrs ((s ,name)) (ff-call *midiShare* :word 0 :ptr s :d0 3 :word))) ;; To register a new MidiShare client application (defmacro MidiOpen (name) "Open a new MidiShare client application with name name. Give a unique reference number." `(with-pstrs ((s ,name)) (ff-call *midiShare* :word 0 :ptr s :d0 4 :word))) (defmacro MidiClose (refNum) "Close an opened MidiShare application from its reference number" `(block nil (ff-call *midiShare* :word ,refNum :d0 5))) ;; To access global informations about a client applications (defmacro MidiGetName (refNum) "Give the name of a MidiShare application from its reference number" `(block nil (%%get-string (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 6 :ptr)))) (defmacro MidiSetName (refNum name) "Change the name of a MidiShare application" `(with-pstrs ((s ,name)) (ff-call *midiShare* :word ,refNum :ptr s :d0 7 ))) (defmacro MidiGetInfo (refNum) "Give the 32-bits user defined content of the info field of a MidiShare application. Analogous to window's refcon." `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 8 :ptr))) (defmacro MidiSetInfo (refNum p) "Set the 32-bits user defined content of the info field of a MidiShare application. Analogous to window's refcon." `(block nil (ff-call *midiShare* :word ,refNum :ptr ,p :d0 9))) (defmacro MidiGetFilter (refNum) "Give a pointer to the input filter record of a MidiShare application. Give NIL if no filter is installed" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 10 :ptr))) (defmacro MidiSetFilter (refNum p) "Install an input filter. The argument p is a pointer to a filter record." `(block nil (ff-call *midiShare* :word ,refNum :ptr ,p :d0 11))) ;; To install real-time alarms (must be C functions) (defmacro MidiGetRcvAlarm (refNum) "Get the adress of the receive alarm" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 #x0C :ptr))) (defmacro MidiSetRcvAlarm (refNum alarm) "Install a receive alarm" `(block nil (ff-call *midiShare* :word ,refNum :ptr ,alarm :d0 #x0D))) (defmacro MidiGetApplAlarm (refNum) "Get the adress of the context alarm" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 #x0E :ptr))) (defmacro MidiSetApplAlarm (refNum alarm) "Install a context alarm" `(block nil (ff-call *midiShare* :word ,refNum :ptr ,alarm :d0 #x0F))) ;; To connect client applications (defmacro MidiConnect (src dst state) "Connect or disconnect two MidiShare applications" `(block nil (ff-call *midiShare* :word ,src :word ,dst :word (if ,state -1 0) :d0 #x10))) (defmacro MidiIsConnected (src dst) "Test if two MidiShare applications are connected" `(not (eq 0 (block nil (ff-call *midiShare* :word 0 :word ,src :word ,dst :d0 #x11 :word))))) ;; To open and close the mac physical ports (defmacro MidiGetPortState (port) "Give the state : open or closed, of a MidiPort" `(not (eq 0 (block nil (ff-call *midiShare* :word 0 :word ,port :d0 #x12 :word))))) (defmacro MidiSetPortState (port state) "Open or close a MidiPort" `(block nil (ff-call *midiShare* :word ,port :word (if ,state -1 0) :d0 #x13))) ;; To create, copy and free MidiShare events (defmacro MidiNewEv (typeNum) "Allocate a new MidiEvent" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,typeNum :d0 #x15 :ptr))) (defmacro MidiCopyEv (ev) "Duplicate a MidiEvent" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :ptr ,ev :d0 #x16 :ptr))) (defmacro MidiFreeEv (ev) "Free a MidiEvent" `(block nil (ff-call *midiShare* :ptr ,ev :d0 #x17))) ;; To know about memory space available for MidiShare events (defmacro MidiFreeSpace () "Amount of free MidiShare cells" `(block nil (ff-call *midiShare* :long 0 :d0 #x14 :long))) (defmacro MidiTotalSpace () "Total amount of Cells" `(block nil (ff-call *midiShare* :long 0 :d0 #x35 :long))) (defmacro MidiGrowSpace (n) "Total amount of Cells" `(block nil (ff-call *midiShare* :long 0 :long ,n :d0 #x36 :long))) ;; To access information fields of MidiShare events (defmacro MidiSetField (ev field val) "Set a field of a MidiEvent" `(block nil (ff-call *midiShare* :ptr ,ev :long ,field :long ,val :d0 #x3A))) (defmacro MidiGetField (ev field) "Get a field of a MidiEvent" `(block nil (ff-call *midiShare* :long 0 :ptr ,ev :long ,field :d0 #x3B :long))) (defmacro MidiAddField (ev val) "Append a field to a MidiEvent (only for sysex and stream)" `(block nil (ff-call *midiShare* :ptr ,ev :long ,val :d0 #x1A))) (defmacro MidiCountFields (ev) "The number of fields of a MidiEvent" `(block nil (ff-call *midiShare* :long 0 :ptr ,ev :d0 #x3C :long))) ;; To create sequences of MidiShare events (defmacro MidiNewSeq () "Allocate an empty sequence" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :d0 #x1D :ptr))) (defmacro MidiAddSeq (seq ev) "Add an event to a sequence" `(block nil (ff-call *midiShare* :ptr ,seq :ptr ,ev :d0 #x1E))) (defmacro MidiFreeSeq (seq) "Free a sequence and its content" `(block nil (ff-call *midiShare* :ptr ,seq :d0 #x1F))) (defmacro MidiClearSeq (seq) "Free only the content of a sequence. The sequence become empty" `(block nil (ff-call *midiShare* :ptr ,seq :d0 #x20))) (defmacro MidiApplySeq (seq proc) "Call a function for every events of a sequence" `(block nil (ff-call *midiShare* :ptr ,seq :ptr ,proc :d0 #x21))) ;; To send and receive MidiShare events ; To send events (defmacro MidiSendIm (refNum ev) "send an event now" `(block nil (ff-call *midiShare* :word ,refNum :ptr ,ev :d0 #x23))) (defmacro MidiSend (refNum ev) "send an event using its own date" `(block nil (ff-call *midiShare* :word ,refNum :ptr ,ev :d0 #x24))) (defmacro MidiSendAt (refNum ev date) "send an event at date <date>" `(block nil (ff-call *midiShare* :word ,refNum :ptr ,ev :long ,date :d0 #x25))) ; To receive events (defmacro MidiCountEvs (refNum) "Give the number of events waiting in the reception fifo" `(block nil (ff-call *midiShare* :long 0 :word ,refNum :d0 #x26 :long))) (defmacro MidiGetEv (refNum) "Read an event from the reception fifo" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 #x27 :ptr))) (defmacro MidiAvailEv (refNum) "Get a pointer to the first event in the reception fifo without removing it" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :word ,refNum :d0 #x28 :ptr))) (defmacro MidiFlushEvs (refNum) "Delete all the events waiting in the reception fifo" `(block nil (ff-call *midiShare* :word ,refNum :d0 #x29))) ; Time Managing and MTC synchronisation (defmacro MidiGetTime () "give the current time" `(block nil (ff-call *midiShare* :long 0 :d0 #x22 :long))) (defmacro MidiGetSyncInfo (syncInfo) "Fill syncInfo record with current synchronisation informations" `(block nil (ff-call *midiShare* :ptr ,syncInfo :d0 #x38))) (defmacro MidiSetSyncMode (mode) "set the MidiShare synchroniation mode" `(block nil (ff-call *midiShare* :word ,mode :d0 #x39))) (defmacro MidiGetExtTime () "give the current external time" `(block nil (ff-call *midiShare* :long 0 :d0 #x3D :long))) (defmacro MidiInt2ExtTime (time) "convert internal time to external time" `(block nil (ff-call *midiShare* :long 0 :long ,time :d0 #x3E :long))) (defmacro MidiExt2IntTime (time) "convert external time to internal time" `(block nil (ff-call *midiShare* :long 0 :long ,time :d0 #x3F :long))) (defmacro MidiTime2Smpte (time format smpteLocation) "convert a time to an Smpte location using format" `(block nil (ff-call *midiShare* :long ,time :short ,format :ptr ,smpteLocation :d0 #x40))) (defmacro MidiSmpte2Time (smpteLocation) "convert an Smpte location to a time" `(block nil (ff-call *midiShare* :long 0 :ptr ,smpteLocation :d0 #x41 :long))) ;; real-time tasks managing (defmacro MidiCall (proc date refNum arg1 arg2 arg3) "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>" `(block nil (ff-call *midiShare* :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2C))) (defmacro MidiTask (proc date refNum arg1 arg2 arg3) "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>. Return a pointer to the corresponding typeProcess event" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2D :ptr))) (defmacro MidiDTask (proc date refNum arg1 arg2 arg3) "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>. Return a pointer to the corresponding typeDProcess event" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2E :ptr))) (defmacro MidiForgetTaskHdl (thdl) "Forget a previously scheduled typeProcess or typeDProcess event created by MidiTask or MidiDTask" `(block nil (ff-call *midiShare* :ptr ,thdl :d0 #x2F))) (defmacro MidiForgetTask (ev) "Forget a previously scheduled typeProcess or typeDProcess event created by MidiTask or MidiDTask" `(without-interrupts (rset *taskHdl* :ttaskHdl.task ,ev) (midiforgetTaskHdl *taskHdl*))) (defmacro MidiCountDTasks (refNum) "Give the number of typeDProcess events waiting" `(block nil (ff-call *midiShare* :long 0 :word ,refNum :d0 #x30 :long))) (defmacro MidiFlushDTasks (refNum) "Remove all the typeDProcess events waiting" `(block nil (ff-call *midiShare* :word ,refNum :d0 #x31))) (defmacro MidiExec1DTask (refNum) "Call the next typeDProcess waiting" `(block nil (ff-call *midiShare* :word ,refNum :d0 #x32))) ;; special functions ; low level memory managing (defmacro MidiNewCell () "Allocate a basic Cell" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :d0 #x33 :ptr))) (defmacro MidiFreeCell (cell) "Delete a basic Cell" `(block nil (ff-call *midiShare* :ptr ,cell :d0 #x34))) ;;mail boxes (defmacro MidiReadSync (adrMem) "Read and clear a memory address (not-interruptible)" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :ptr ,adrMem :d0 #x2A :ptr))) (defmacro MidiWriteSync (adrMem val) "write if nil into a memory address (not-interruptible)" `(block nil (ff-call *midiShare* :ptr (%null-ptr) :ptr ,adrMem :ptr ,val :d0 #x2B :ptr)))